<template>
  <div id="subLine-controller">
    <div class="item-wrapper">
      <div class="item" v-for="item in subLineData" @click.stop="handleItemClick(item)">
        <div class="box" :style="{ borderColor: item.color, backgroundColor: [item.isShow ? item.color : 'transparent'] }"></div>
        <span :style="{ color: '#34c5cf' }">{{ item.name.slice(-3) }}</span>
      </div>
    </div>
  </div>
  <div class="active-panel">
    <div class="header">
      <strong>发展历程</strong>
      <div class="controler">
        <i class="iconfont metro-pause" @click="pause"></i>
        <i class="iconfont metro-play" @click="play"></i>
        <i class="iconfont metro-icon-replay-copy" @click="replay"></i>
      </div>
    </div>
    <div class="content">
      <a-slider
        style="width: 500px"
        v-if="resPaths.length !== 0"
        v-model:value="currentTime"
        :marks="marks"
        :step="0.5"
        :min="0"
        :max="max"
        :disabled="true"
      >
      </a-slider>
    </div>
    <div class="message" v-if="message.length">
      {{ message }}
    </div>
  </div>
</template>

<script setup>
import * as Cesium from 'cesium';
import { onMounted, ref, onBeforeUnmount, watch } from 'vue';
import { useLineData, removeAllStations } from '@/store';
import { flattenPositions } from '@/cesiumTools/core';
import { flyToDefaultView, renderAll, removeByCacheData, removeAllBillboards } from '@/cesiumTools/effectController';
import { line_history } from '@/store/staticData';
import { polygon, centroid } from 'turf';

const currentTime = ref(0);
const marks = ref({});
const max = ref(100);
const message = ref('');
const lineDataStore = useLineData();
const subLineData = ref([]);
// 地铁线的路径数组
let curPaths = [];
let resPaths = [];
let isAnimate = false;
let viewer;
// 进入的时候隐藏所有地铁线路,并跳转到默认点
onMounted(() => {
  viewer = lineDataStore.Viewer;
  subLineData.value = lineDataStore.allData;
  subLineData.value.forEach(item => {
    item.isShow = false;
  });
  // 将站点站线全部隐藏
  const lineNames = lineDataStore.allData.map(item => item.name);
  lineDataStore.displayLine(lineNames, false);
  removeAllStations(viewer);
  removeAllBillboards();
  // 暂时禁用全局管理，unMount的时候打开
  lineDataStore.disableController(true);
});

onBeforeUnmount(() => {
  pause();
  // 清除已经有的数据以及实体
  removeByCacheData(viewer, dataEnts);
  dataEnts = null;
  // 全局管理恢复，路线展示恢复
  lineDataStore.disableController(false);
  // 将站点站线全部展示
  const lineNames = lineDataStore.allData.map(item => item.name);
  lineDataStore.displayLine(lineNames, true);
});

const removeCurrentEnts = () => {
  // 清除已经有的数据以及实体
  removeByCacheData(viewer, dataEnts);
  dataEnts = {};
};

let centerMarker;
const calculateRouteCenterView = positions => {
  if (positions.length) {
    // 清理之前的标记点
    if (centerMarker) {
      viewer.entities.remove(centerMarker);
      centerMarker = null;
    }

    // 获取坐标
    const geoCoords = positions.map(item => [item.lng, item.lat]);
    // 闭合多边形
    geoCoords.push(geoCoords[0]);

    // 计算多边形
    const routePolygon = polygon([geoCoords]);
    const routeCentroid = centroid(routePolygon);

    const [centerLng, centerLat] = routeCentroid.geometry.coordinates;

    // 创建视角标记点
    centerMarker = viewer.entities.add({
      name: 'centerMarker',
      position: Cesium.Cartesian3.fromDegrees(centerLng, centerLat, 15000),
      point: {
        color: Cesium.Color.TRANSPARENT,
        pixelSize: 1,
      },
    });

    // 飞行到中心点
    viewer.flyTo(centerMarker, {
      // HeadingPitchRange(航向、俯仰、距离范围):
      offset: new Cesium.HeadingPitchRange(Cesium.Math.toRadians(80), Cesium.Math.toRadians(-70), 50000),
      // duration(飞行时间):
      duration: 1.5,
    });
  }
};

// 点击对应线路，视角跳转，并重新渲染该线路，id要不一样，路线坐标使用callbackProperty
// dataEnts类型 {
//   lineEnts:[],
//   stationEnts:[],
//   billboards:[]
// }
let dataEnts = {};
const handleItemClick = item => {
  subLineData.value.forEach(item => {
    item.isShow = false;
  });
  item.isShow = true;
  const { id, paths } = item;
  const positions = flattenPositions(paths);

  // 添加视角跳转到线路中心
  calculateRouteCenterView(paths);
  // flyToDefaultView(viewer);

  pause();
  removeCurrentEnts();
  const target = line_history.find(n => n.id === id);
  if (target) {
    pause();
    currentTime.value = 0;
    // 渲染站点站线,不走内部缓存,要获取返回值，在外部进行管理
    dataEnts = renderAll(viewer, [item], false);
    // 渲染时间slider
    const { history } = target;
    // 调整max的计算方式
    max.value = (history.length - 1) * 10;
    let res = {};
    history.forEach((item, index) => {
      res[index * 10] = {
        style: {
          color: '#fff',
          fontSize: 10,
        },
        label: item.timePoint,
        message: item.message,
      };
    });
    // 给播放控件赋值，并给路径数据赋值
    marks.value = res;
    resPaths = positions;
    curPaths = positions.slice(0, 2);

    // 找到路线的实体，并给其坐标重新赋值
    const entity = dataEnts.lineEnts[0];
    entity.polyline.positions = new Cesium.CallbackProperty(() => Cesium.Cartesian3.fromDegreesArray(curPaths), false);

    // 自动开始播放
    play();
  }
};

const pause = () => {
  isAnimate = false;
};

let myRequestID = null;
const play = () => {
  // 将之前的动画帧清除
  cancelAnimationFrame(myRequestID);
  const animate = () => {
    if (isAnimate) {
      currentTime.value += 0.1;
      const rate = currentTime.value / max.value;
      let index = Math.ceil(rate * resPaths.length);
      // 我们的坐标两个为一组，不为双数的话，就加一
      if (index % 2 !== 0) {
        index = index + 1;
      }
      // 如果是最后一个坐标，就返回
      if (index >= resPaths.length - 1) {
        curPaths = resPaths;
        isAnimate = false;
        return;
      }

      curPaths = resPaths.slice(0, index);
      myRequestID = requestAnimationFrame(animate);
    }
  };
  isAnimate = true;
  animate();
};

const replay = () => {
  pause();
  currentTime.value = 0;
  curPaths = resPaths.slice(0, 2);
  play();
};

// 监听当前进度
// 1.找到当前进度在marks当中的下标
// 2.通过下标,找message
watch(currentTime, val => {
  let targetIndex = null;
  const markKeys = Object.keys(marks.value).map(n => Number(n));
  const markValues = Object.values(marks.value);
  markKeys.forEach((m, index) => {
    // 判断val是否在值区间
    if (index > 0 && val <= m && val > markKeys[index - 1]) {
      targetIndex = index;
    }

    if (val <= m && index === 0) {
      targetIndex = index;
    }
  });
  if (targetIndex) {
    const result = markValues[targetIndex];
    message.value = result.message;
  } else {
    message.value = '';
  }
});
</script>

<style lang="scss" scoped>
#subLine-controller {
  position: absolute;
  bottom: 90px;
  left: 32%;
  transform: translateX(-50%);
  width: 7.625vw;
  height: 7.292vw;
  background-color: rgba(0, 0, 0, 0.3);
  border: 1px solid #664a16;
  padding: 4px;
  display: flex;
  flex-direction: column;
  z-index: 1000;
  user-select: none; /* 阻止文本选中 */
  -webkit-user-select: none; /* 兼容 Safari */
  -moz-user-select: none; /* 兼容 Firefox */
  -ms-user-select: none; /* 兼容 IE/Edge */
}

.box {
  width: 10px;
  height: 10px;
  border-width: 1px;
  border-style: solid;
  background: transparent;
  user-select: all;
  cursor: pointer;
}

.item {
  width: 3.385vw;
  height: 1.042vw;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 0.156vw;
  background-color: rgba(255, 255, 255, 0.2);
  border: 1px solid #885f12;
  color: #fff;
  font-size: 0.521vw;
  pointer-events: all;
  cursor: pointer;
}

.item:hover {
  border: 1px solid #d8961a;
}

.item > span {
  line-height: 0.469vw;
}

.item > input {
  outline: none;
  border: none;
  transition: all 0.3s ease;
}

.item-wrapper {
  display: flex;
  justify-content: space-between;
  align-content: space-around;
  flex-wrap: wrap;
  flex: 1;
}

.active-panel {
  width: 580px;
  height: 170px;
  border: 1px solid #ab7818;
  background-color: rgba(0, 0, 0, 0.3);
  position: absolute;
  left: 37%;
  bottom: 90px;
  color: #fff;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  z-index: 1000;
  user-select: none; /* 阻止文本选中 */
  -webkit-user-select: none; /* 兼容 Safari */
  -moz-user-select: none; /* 兼容 Firefox */
  -ms-user-select: none; /* 兼容 IE/Edge */
}

.active-panel > .header {
  height: 1.563vw;
  padding: 0.208vw;

  margin-bottom: -0.521vw;
  font-family: '等线Bold';
  display: flex;
  gap: 390px;
}

.active-panel > .header > strong {
  background: rgb(255, 255, 255);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 1) 9%, rgba(211, 156, 50, 1) 57%);
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

.controler {
  width: 100px;
  display: flex;
  align-items: center;
  justify-content: space-around;
  i {
    cursor: pointer;
    pointer-events: all;
    font-size: 20px;
  }
}

.controler > i:hover {
  background: rgb(255, 255, 255);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 1) 9%, rgba(211, 156, 50, 1) 57%);
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

.active-panel > .header > strong {
  font-weight: normal;
  margin-right: 0.521vw;
}

.active-panel > .header > span {
  font-size: 0.625vw;
}

.content {
  flex: 1;
  padding: 0 30px;
  margin-top: 30px;
}

.message {
  position: absolute;
  bottom: 26px;
  left: 50%;
  transform: translateX(-50%);
  background-color: rgba(0, 0, 0, 0.3);
  color: #fff;
  text-align: center;
}
</style>
